package com.engine.salary.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.encrypt.EncryptUtil;
import com.engine.salary.entity.siarchives.param.InsuranceArchivesListParam;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesEmployeePO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesFundSchemePO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesOtherSchemePO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesSocialSchemePO;
import com.engine.salary.entity.sicategory.po.ICategoryPO;
import com.engine.salary.entity.sischeme.po.InsuranceSchemePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.siaccount.EmployeeStatusEnum;
import com.engine.salary.enums.sicategory.WelfareTypeEnum;
import com.engine.salary.mapper.siarchives.SocialSchemeMapper;
import com.engine.salary.mapper.sicategory.ICategoryMapper;
import com.engine.salary.mapper.sischeme.InsuranceSchemeMapper;
import com.engine.salary.mapper.taxagent.TaxAgentMapper;
import com.engine.salary.service.SIArchivesService;
import com.engine.salary.service.SIImportService;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.excel.ExcelComment;
import com.engine.salary.util.excel.ExcelUtilPlus;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.conn.mybatis.MyBatisFactory;
import weaver.hrm.User;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author weaver_cl
 * @Description:
 * @Date 2022/4/20
 * @Version V1.0
 **/
public class SIImportServiceImpl extends Service implements SIImportService {
    private EncryptUtil encryptUtil = new EncryptUtil();

//    private SIArchivesBiz siArchivesBiz = new SIArchivesBiz();

    public SIArchivesService getSIArchivesService(User user) {
        return ServiceUtil.getService(SIArchivesServiceImpl.class,user);
    }

    private ICategoryMapper getICategoryMapper() {
        return MapperProxyFactory.getProxy(ICategoryMapper.class);
    }

    private TaxAgentMapper getTaxAgentMapper() {
        return MapperProxyFactory.getProxy(TaxAgentMapper.class);
    }

    private InsuranceSchemeMapper getInsuranceSchemeMapper() {
        return MapperProxyFactory.getProxy(InsuranceSchemeMapper.class);
    }

    @Override
    public XSSFWorkbook exportTemplate(InsuranceArchivesListParam param) {
        //工作簿list
        List<List<Object>> excelSheetData = new ArrayList<>();
        Boolean exportData = param.getExportData();

        //工作簿名称
        String sheetName;
        //表头
        if (param.isExtWelArchiveList()) {
            sheetName = SalaryI18nUtil.getI18nLabel(542679, "非系统人员");
        } else if (param.getRunStatuses().size() > 0) {
            if (param.getRunStatuses().contains(EmployeeStatusEnum.STAY_ADD.getValue()) && param.getRunStatuses().size() == 1) {
                sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + EmployeeStatusEnum.STAY_ADD.getDefaultLabel());
            } else if (param.getRunStatuses().contains(EmployeeStatusEnum.PAYING.getValue()) && param.getRunStatuses().contains(EmployeeStatusEnum.STAY_DEL.getValue()) && param.getRunStatuses().size() == 2) {
                sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + "在缴员工");
            } else if (param.getRunStatuses().contains(EmployeeStatusEnum.STAY_DEL.getValue()) && param.getRunStatuses().size() == 1) {
                sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + EmployeeStatusEnum.STAY_DEL.getDefaultLabel());
            } else if (param.getRunStatuses().contains(EmployeeStatusEnum.STOP_PAYMENT_FROM_ADD.getValue()) && param.getRunStatuses().contains(EmployeeStatusEnum.STOP_PAYMENT_FROM_DEL.getValue()) && param.getRunStatuses().size() == 2) {
                sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板" + "-" + "停缴员工");
            } else {
                sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板");
            }
        } else {
            sheetName = SalaryI18nUtil.getI18nLabel(85368, "社保福利档案导入模板");
        }


        List<String> headers = buildHeader();
        InsuranceArchivesListParam request = InsuranceArchivesListParam.builder().build();
        if (param.getHireDate() != null && param.getHireDate().length == 2) {
            param.setHiredateStart(param.getHireDate()[0]);
            param.setHiredateEnd(param.getHireDate()[1]);
        }
        if (param.getDimissionDate() != null && param.getDimissionDate().length == 2) {
            param.setDimissionDateStart(param.getDimissionDate()[0]);
            param.setDimissionDateEnd(param.getDimissionDate()[1]);
        }
        if (Objects.equals("fromQuickSearch", param.getDataSource())) {
            if (StringUtils.isNotBlank(param.getStatusesStr())) {
                request.setStatuses(Arrays.stream(param.getStatusesStr().split(",")).map(String::new).collect(Collectors.toList()));
            }
            request.setKeyword(param.getUserName());
            request.setStartNum(param.getStartNum());
            request.setPageSize(param.getPageSize());
        } else {
            request = param;
        }
//        request.setPageSize(null);
//        request.setStartNum(null);
//        List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS = getSIArchivesService(user).listPageEmployeePOS(request);
//        if (insuranceArchivesEmployeePOS == null) {
//            insuranceArchivesEmployeePOS = new ArrayList<>();
//        }
//        List<Map<String, Object>> datas = buildTableData(insuranceArchivesEmployeePOS);
        //表头
        excelSheetData.add(Arrays.asList(headers.toArray(new String[0])));
        /**
         * 导出数据
         */
        if (exportData != null && exportData){
            //查询总页数
            SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession();
            SocialSchemeMapper socialSchemeMapper = sqlSession.getMapper(SocialSchemeMapper.class);
            List<InsuranceArchivesEmployeePO> page = new ArrayList<>();
            if (param.isExtWelArchiveList()) {
                page = socialSchemeMapper.queryExtEmployeeList(param);
            } else {
                page = socialSchemeMapper.queryEmployeeList(param);
            }
            PageInfo<InsuranceArchivesEmployeePO> pageInfo = SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(),
                    page, InsuranceArchivesEmployeePO.class);
            int total = (int)pageInfo.getTotal();
            param.setPageSize(total);
            param.setCurrent(1);
            if (CollectionUtils.isNotEmpty(param.getDepartmentIds())) {
                param.setDepartmentIdsStr(StringUtils.join(param.getDepartmentIds(), ","));
            }
            if (CollectionUtils.isNotEmpty(param.getSubcompanyIds())) {
                param.setSubcompanyIdsStr(StringUtils.join(param.getSubcompanyIds(), ","));
            }
            if (CollectionUtils.isNotEmpty(param.getPositions())) {
                param.setPositionsStr(StringUtils.join(param.getPositions(), ","));
            }
            if (CollectionUtils.isNotEmpty(param.getStatuses())) {
                param.setStatusesStr(StringUtils.join(param.getStatuses(), ","));
            }

            Map<String, Object> dataMap = getSIArchivesService(user).listPage(param);
            List<Map<String, Object>> records = (List<Map<String, Object>>)dataMap.get("datas");
            List<WeaTableColumn> columns = (List<WeaTableColumn>)dataMap.get("columns");
            List<String> rowCloumn = Lists.newArrayList();
            List<String> names = columns.stream().map(WeaTableColumn::getText).collect(Collectors.toList());
            headers.forEach(header -> {
                if (names.contains(header)){
                    columns.forEach(column -> {
                        //用来判断columns中是否包含header
                        if (header.equals(column.getText())){
                            rowCloumn.add(column.getColumn());
                        }
                    });
                }else {
                    rowCloumn.add("");
                }
            });
            records.forEach(record -> {
                List<Object> row = Lists.newArrayList();
                rowCloumn.forEach(column -> {
                    if (record.get(column) == null){
                        row.add("");
                    }else {
                        row.add(record.get(column));
                    }
                });
                excelSheetData.add(row);
            });
        }

        // 3.表数据

        // 4.注释
        List<ExcelComment> excelComments = Lists.newArrayList();
        excelComments.add(new ExcelComment(0, 0, 1, 2, SalaryI18nUtil.getI18nLabel(100344, "必填")));
        excelComments.add(new ExcelComment(8, 0, 9, 2, SalaryI18nUtil.getI18nLabel(100344, "社保,公积金,其他福利方案名称不可同时为空")));


        //工作簿数据
        return ExcelUtilPlus.genWorkbookV2(excelSheetData, sheetName,excelComments);
    }


    /**
     * 构建档案excel的表头
     *
     * @return
     */
    public List<String> buildHeader() {
//        boolean welBaseDiffSign = siArchivesBiz.isDiffWelBase();
        boolean welBaseDiffSign = getSIArchivesService(user).isDiffWelBase();
        List<String> result = new ArrayList<>();
        result.add(SalaryI18nUtil.getI18nLabel( 85429, "姓名"));
        result.add(SalaryI18nUtil.getI18nLabel( 86184, "个税扣缴义务人"));
        result.add(SalaryI18nUtil.getI18nLabel( 0, "分部"));
        result.add(SalaryI18nUtil.getI18nLabel( 86185, "部门"));
        result.add(SalaryI18nUtil.getI18nLabel( 86186, "手机号"));
        result.add(SalaryI18nUtil.getI18nLabel( 86187, "员工状态"));
        result.add(SalaryI18nUtil.getI18nLabel(86317, "工号"));
        result.add(SalaryI18nUtil.getI18nLabel(86317, "证件号码"));
        result.add(SalaryI18nUtil.getI18nLabel( 91323, "社保方案名称"));
       // result.add(SalaryI18nUtil.getI18nLabel( 91325, "社保缴纳组织"));
        //社保福利基数
        Map<String, Long> socialMap = welfareNameIdMap( WelfareTypeEnum.SOCIAL_SECURITY);
        if (welBaseDiffSign) {
            socialMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数") + SalaryI18nUtil.getI18nLabel( 0, "个人")));
            socialMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数") + SalaryI18nUtil.getI18nLabel( 0, "单位")));
        } else {
            socialMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数")));
        }

        result.add(SalaryI18nUtil.getI18nLabel( 91324, "社保账号"));
        result.add(SalaryI18nUtil.getI18nLabel( 91319, "社保起始缴纳月"));
        result.add(SalaryI18nUtil.getI18nLabel( 91320, "社保最后缴纳月"));
        result.add(SalaryI18nUtil.getI18nLabel( 91485, "公积金方案名称"));
      //  result.add(SalaryI18nUtil.getI18nLabel( 91488, "公积金缴纳组织"));
        result.add(SalaryI18nUtil.getI18nLabel( 91486, "公积金账号"));
        //公积金福利基数
        Map<String, Long> fundMap = welfareNameIdMap( WelfareTypeEnum.ACCUMULATION_FUND);
        if (welBaseDiffSign) {
            fundMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数") + SalaryI18nUtil.getI18nLabel( 0, "个人")));
            fundMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数") + SalaryI18nUtil.getI18nLabel( 0, "单位")));
        } else {
            fundMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数")));
        }

        result.add(SalaryI18nUtil.getI18nLabel( 91487, "补充公积金账号"));
        result.add(SalaryI18nUtil.getI18nLabel( 91483, "公积金起始缴纳月"));
        result.add(SalaryI18nUtil.getI18nLabel( 91484, "公积金最后缴纳月"));
        result.add(SalaryI18nUtil.getI18nLabel( 91496, "其他福利方案名称"));
      //  result.add(SalaryI18nUtil.getI18nLabel( 91497, "其他福利缴纳组织"));
        //其他福利基数
        Map<String, Long> otherMap = welfareNameIdMap( WelfareTypeEnum.OTHER);
        if (welBaseDiffSign) {
            otherMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数") + SalaryI18nUtil.getI18nLabel( 0, "个人")));
            otherMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数") + SalaryI18nUtil.getI18nLabel( 0, "单位")));
        } else {
            otherMap.forEach((k, v) -> result.add(k + SalaryI18nUtil.getI18nLabel( 0, "申报基数")));
        }

        result.add(SalaryI18nUtil.getI18nLabel( 91490, "其他福利起始缴纳月"));
        result.add(SalaryI18nUtil.getI18nLabel( 91494, "其他福利最后缴纳月"));
        return result;
    }

    /**
     * 获取福利类型名称-id的map
     *
     * @param welfareTypeEnum
     * @return
     */
    public Map<String, Long> welfareNameIdMap(WelfareTypeEnum welfareTypeEnum) {
//        return getICategoryMapper().listByWelfareType(welfareTypeEnum.getValue(),null).stream().collect(Collectors.toMap(ICategoryPO::getInsuranceName, ICategoryPO::getId));
        return getICategoryMapper().listByWelfareType(welfareTypeEnum.getValue(),null)
                .stream()
                .sorted(Comparator.comparing(ICategoryPO::getId))
                .collect(LinkedHashMap::new, (map, item) -> map.put(item.getInsuranceName(), item.getId()), LinkedHashMap::putAll);
    }

    public Map<Long, String> welfareMap() {
        return getICategoryMapper().listAll().stream().collect(Collectors.toMap(ICategoryPO::getId, ICategoryPO::getInsuranceName));
    }

    /**
     * 获取缴纳组织id-名称集合
     *
     * @return
     */
    public Map<Long, String> paymentOrganizationIdNameMap() {
        List<TaxAgentPO> list = getTaxAgentMapper().listAll();
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.toMap(TaxAgentPO::getId, TaxAgentPO::getName));
    }

    public List<Map<String, Object>> buildTableData(List<InsuranceArchivesEmployeePO> insuranceArchivesEmployeePOS) {
        List<Map<String, Object>> records = new ArrayList<>();
        //获取id,福利名称的map，用于下面组装福利数据
        Map<Long, String> welfareMap = welfareMap();
        //获取缴纳组织id-name集合
        Map<Long, String> paymentMap = paymentOrganizationIdNameMap();
        //获取id,方案名称的map，用于下面组装福利数据
        Map<Long, String> schemeMap = new HashMap<>();
        List<InsuranceSchemePO> schemeList = getInsuranceSchemeMapper().listAll();
        if (CollectionUtils.isNotEmpty(schemeList)) {
            schemeMap = schemeList.stream().collect(Collectors.toMap(InsuranceSchemePO::getId, InsuranceSchemePO::getSchemeName));
        }
        List<Long> employeeIds = insuranceArchivesEmployeePOS.stream().map(InsuranceArchivesEmployeePO::getEmployeeId).collect(Collectors.toList());
        Map<Long, InsuranceArchivesSocialSchemePO> socialSchemePOMap = new HashMap<>();
//        List<InsuranceArchivesSocialSchemePO> socialSchemePOList = siArchivesBiz.getSocialByEmployeeIds(employeeIds);
        List<InsuranceArchivesSocialSchemePO> socialSchemePOList = getSIArchivesService(user).getSocialByEmployeeIds(employeeIds);
        encryptUtil.decryptList(socialSchemePOList, InsuranceArchivesSocialSchemePO.class);
        if (CollectionUtils.isNotEmpty(socialSchemePOList)) {
            socialSchemePOMap = socialSchemePOList.stream().collect(Collectors.toMap(InsuranceArchivesSocialSchemePO::getEmployeeId, Function.identity()));
        }
//        List<InsuranceArchivesFundSchemePO> fundSchemePOList = siArchivesBiz.getFundByEmployeeIds(employeeIds);
        List<InsuranceArchivesFundSchemePO> fundSchemePOList = getSIArchivesService(user).getFundByEmployeeIds(employeeIds);
        encryptUtil.encryptList(fundSchemePOList, InsuranceArchivesFundSchemePO.class);
        Map<Long, InsuranceArchivesFundSchemePO> fundSchemePOMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(fundSchemePOList)) {
            fundSchemePOMap = fundSchemePOList.stream().collect(Collectors.toMap(InsuranceArchivesFundSchemePO::getEmployeeId, Function.identity()));
        }
        Map<Long, InsuranceArchivesOtherSchemePO> otherSchemePOMap = new HashMap<>();
//        List<InsuranceArchivesOtherSchemePO> otherSchemePOList = siArchivesBiz.getOtherByEmployeeIds(employeeIds);
        List<InsuranceArchivesOtherSchemePO> otherSchemePOList = getSIArchivesService(user).getOtherByEmployeeIds(employeeIds);
        encryptUtil.decryptList(otherSchemePOList, InsuranceArchivesOtherSchemePO.class);
        if (CollectionUtils.isNotEmpty(otherSchemePOList)) {
            otherSchemePOMap = otherSchemePOList.stream().collect(Collectors.toMap(InsuranceArchivesOtherSchemePO::getEmployeeId, Function.identity()));
        }
        for (InsuranceArchivesEmployeePO item : insuranceArchivesEmployeePOS) {
            InsuranceArchivesSocialSchemePO socialItem = socialSchemePOMap.get(item.getEmployeeId());
            InsuranceArchivesFundSchemePO fundItem = fundSchemePOMap.get(item.getEmployeeId());
            InsuranceArchivesOtherSchemePO otherItem = otherSchemePOMap.get(item.getEmployeeId());
            Map<String, Object> map = new HashMap<>();
            map.put(SalaryI18nUtil.getI18nLabel( 85429, "姓名"), item.getUserName());
            map.put(SalaryI18nUtil.getI18nLabel( 86185, "部门"), item.getDepartmentName());
            map.put(SalaryI18nUtil.getI18nLabel( 86186, "手机号"), item.getTelephone());
            map.put(SalaryI18nUtil.getI18nLabel( 86187, "员工状态"), item.getUserStatusEnum() == null ? "" : item.getUserStatusEnum().getDefaultLabel());
            if (socialItem != null) {
                map.put(SalaryI18nUtil.getI18nLabel( 91323, "社保方案名称"), schemeMap.get(socialItem.getSocialSchemeId()));
                map.put(SalaryI18nUtil.getI18nLabel( 91325, "社保缴纳组织"), paymentMap.get(socialItem.getPaymentOrganization()));
                Map<String, Object> socialJson = JSON.parseObject(socialItem.getSocialPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                });
                if (socialJson != null) {
                    socialJson.forEach((k, v) -> map.put(welfareMap.get(Long.valueOf(k)) + SalaryI18nUtil.getI18nLabel( 100293, "申报基数"), v));
                }
                map.put(SalaryI18nUtil.getI18nLabel( 91324, "社保账号"), socialItem.getSocialAccount());
                map.put(SalaryI18nUtil.getI18nLabel( 91319, "社保起始缴纳月"), socialItem.getSocialStartTime());
                map.put(SalaryI18nUtil.getI18nLabel( 91320, "社保最后缴纳月"), socialItem.getSocialEndTime());
            }
            if (fundItem != null) {
                map.put(SalaryI18nUtil.getI18nLabel( 91485, "公积金方案名称"), schemeMap.get(fundItem.getFundSchemeId()));
                map.put(SalaryI18nUtil.getI18nLabel( 91488, "公积金缴纳组织"), paymentMap.get(fundItem.getPaymentOrganization()));
                map.put(SalaryI18nUtil.getI18nLabel( 91486, "公积金账号"), fundItem.getFundAccount());
                Map<String, Object> fundJson = JSON.parseObject(fundItem.getFundPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                });
                if (fundJson != null) {
                    fundJson.forEach((k, v) -> map.put(welfareMap.get(Long.valueOf(k)) + SalaryI18nUtil.getI18nLabel( 100293, "申报基数"), v));
                }
                map.put(SalaryI18nUtil.getI18nLabel( 91487, "补充公积金账号"), fundItem.getSupplementFundAccount());
                map.put(SalaryI18nUtil.getI18nLabel( 91483, "公积金起始缴纳月"), fundItem.getFundStartTime());
                map.put(SalaryI18nUtil.getI18nLabel( 91484, "公积金最后缴纳月"), fundItem.getFundEndTime());

            }
            if (otherItem != null) {
                map.put(SalaryI18nUtil.getI18nLabel( 91496, "其他福利方案名称"), schemeMap.get(otherItem.getOtherSchemeId()));
                map.put(SalaryI18nUtil.getI18nLabel( 91497, "其他福利缴纳组织"), paymentMap.get(otherItem.getPaymentOrganization()));
                Map<String, Object> otherJson = JSON.parseObject(otherItem.getOtherPaymentBaseString(), new TypeReference<Map<String, Object>>() {
                });
                if (otherJson != null) {
                    otherJson.forEach((k, v) -> map.put(welfareMap.get(Long.valueOf(k)) + SalaryI18nUtil.getI18nLabel( 100293, "申报基数"), v));
                }
                map.put(SalaryI18nUtil.getI18nLabel( 91490, "其他福利起始缴纳月"), otherItem.getOtherStartTime());
                map.put(SalaryI18nUtil.getI18nLabel( 91494, "其他福利最后缴纳月"), otherItem.getOtherEndTime());
            }
            records.add(map);
        }
        return records;
    }

}
